/**
 * Classes.java 9:22:44 AM Apr 23, 2012
 *
 * Copyright(c) 2000-2012 HC360.COM, All Rights Reserved.
 */
package jbase.project.system.test;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
 * <p>
 * 基于asm的工具类
 * </p>
 * 
 * @author dixingxing
 * @date Apr 23, 2012
 */
public final class Asm {

	private Asm() {
		
	}

	/**
	 * 
	 * <p>
	 * 比较参数类型是否一致
	 * </p>
	 * 
	 * @param types
	 *            asm的类型({@link Type})
	 * @param clazzes
	 *            java 类型({@link Class})
	 * @return
	 */
	private static boolean sameType(Type[] types, Class<?>[] clazzes) {
		// 个数不同
		if (types.length != clazzes.length) {
			return false;
		}

		for (int i = 0; i < types.length; i++) {
			if (!Type.getType(clazzes[i]).equals(types[i])) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 
	 * <p>
	 * 获取方法的参数名
	 * </p>
	 * 
	 * @param m
	 * @return
	 */
	public static String[] getMethodParamNames(final Method m) {
		final String[] paramNames = new String[m.getParameterTypes().length];
		final String n = m.getDeclaringClass().getName();
		ClassReader cr = null;
		try {
			cr = new ClassReader(n);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		cr.accept(new ClassVisitor() {

			@Override
			public void visitSource(String arg0, String arg1) {

				// TODO Auto-generated method stub

			}

			@Override
			public void visitOuterClass(String arg0, String arg1, String arg2) {

				// TODO Auto-generated method stub

			}

			@Override
			public MethodVisitor visitMethod(int access, final String methodName, String desc, String signature,
					String[] exceptions) {
				System.out.printf("access:%d\nname:%s\ndesc:%s\nsignature:%s\nexceptions:%s\n", access, methodName,
						desc, signature, exceptions);
				return new MethodVisitor() {

					@Override
					public void visitVarInsn(int var1, int var2) {
						System.out.printf("VarInsn:%d,%d\n", var1, var2);
					}

					@Override
					public void visitTypeInsn(int arg0, String arg1) {

					}

					@Override
					public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2, String arg3) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label[] arg3) {

						// TODO Auto-generated method stub

					}

					@Override
					public AnnotationVisitor visitParameterAnnotation(int arg0, String arg1, boolean arg2) {

						// TODO Auto-generated method stub
						return null;
					}

					@Override
					public void visitMultiANewArrayInsn(String arg0, int arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitMaxs(int arg0, int arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitLocalVariable(String varName, String varType, String signature, Label label,
							Label labelx, int index) {
						System.out.println("++++++++++++++++++++++++++++++++++++");
						System.out.println("method:" + methodName);
						System.out.println("--->" + varName);
						System.out.println("--->" + varType);
						System.out.println("--->" + signature);
						System.out.println("--->" + label);
						System.out.println("--->" + labelx);
						System.out.println("--->" + index);
						// TODO Auto-generated method stub

					}

					@Override
					public void visitLineNumber(int arg0, Label arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitLdcInsn(Object arg0) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitLabel(Label arg0) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitJumpInsn(int arg0, Label arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitIntInsn(int arg0, int arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitInsn(int arg0) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitIincInsn(int arg0, int arg1) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitEnd() {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitCode() {

						// TODO Auto-generated method stub

					}

					@Override
					public void visitAttribute(Attribute arg0) {

						// TODO Auto-generated method stub

					}

					@Override
					public AnnotationVisitor visitAnnotationDefault() {

						// TODO Auto-generated method stub
						return null;
					}

					@Override
					public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {

						// TODO Auto-generated method stub
						return null;
					}
				};
			}

			@Override
			public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {

				// TODO Auto-generated method stub

			}

			@Override
			public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) {

				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public void visitEnd() {

				// TODO Auto-generated method stub

			}

			@Override
			public void visitAttribute(Attribute arg0) {

				// TODO Auto-generated method stub

			}

			@Override
			public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {

				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public void visit(int arg0, int arg1, String arg2, String arg3, String arg4, String[] arg5) {

				// TODO Auto-generated method stub

			}
		}, 0);
		/**
		 * cr.accept(new ClassVisitor(Opcodes.ASM4) {
		 * 
		 * @Override public MethodVisitor visitMethod(final int access, final
		 *           String name, final String desc, final String signature,
		 *           final String[] exceptions) { final Type[] args =
		 *           Type.getArgumentTypes(desc); if (!name.equals(m.getName())
		 *           || !sameType(args, m.getParameterTypes())) { return
		 *           super.visitMethod(access, name, desc, signature,
		 *           exceptions); } MethodVisitor v = super.visitMethod(access,
		 *           name, desc, signature, exceptions); return new
		 *           MethodVisitor(Opcodes.ASM4, v) {
		 * @Override public void visitLocalVariable(String name, String desc,
		 *           String signature, Label start, Label end, int index) { int
		 *           i = index - 1; if (Modifier.isStatic(m.getModifiers())) { i
		 *           = index; } if (i >= 0 && i < paramNames.length) {
		 *           paramNames[i] = name; } super.visitLocalVariable(name,
		 *           desc, signature, start, end, index); }
		 * 
		 *           }; }
		 * 
		 * @Override public void visit(int arg0, int arg1, String arg2, String
		 *           arg3, String arg4, String[] arg5) {
		 * 
		 *           }
		 * 
		 * @Override public AnnotationVisitor visitAnnotation(String arg0,
		 *           boolean arg1) {
		 * 
		 *           // TODO Auto-generated method stub return null; }
		 * 
		 * @Override public void visitAttribute(Attribute arg0) {
		 * 
		 *           // TODO Auto-generated method stub
		 * 
		 *           }
		 * 
		 * @Override public void visitEnd() {
		 * 
		 *           // TODO Auto-generated method stub
		 * 
		 *           }
		 * 
		 * @Override public FieldVisitor visitField(int arg0, String arg1,
		 *           String arg2, String arg3, Object arg4) {
		 * 
		 *           // TODO Auto-generated method stub return null; }
		 * 
		 * @Override public void visitInnerClass(String arg0, String arg1,
		 *           String arg2, int arg3) {
		 * 
		 *           // TODO Auto-generated method stub
		 * 
		 *           }
		 * 
		 * @Override public void visitOuterClass(String arg0, String arg1,
		 *           String arg2) {
		 * 
		 *           // TODO Auto-generated method stub
		 * 
		 *           }
		 * 
		 * @Override public void visitSource(String arg0, String arg1) {
		 * 
		 *           // TODO Auto-generated method stub
		 * 
		 *           } }, 0);
		 */
		return paramNames;
	}

	public static void main(String[] args) throws SecurityException, NoSuchMethodException {
		// String[] s =
		// getMethodParamNames(Asm.class.getMethod("getMethodParamNames",
		// Method.class));
		// System.out.println(Arrays.toString(s));
		//
		// s = getMethodParamNames(Asm.class.getDeclaredMethod("sameType",
		// Type[].class, Class[].class));
		// System.out.println(Arrays.toString(s));
		//
		// s =
		// getMethodParamNames(MethodVisitor.class.getDeclaredMethod("visitAnnotation",
		// String.class, Boolean.TYPE));
		// System.out.println(Arrays.toString(s));

		String[] sx = getMethodParamNames(ClassTest.class.getMethod("init", String.class));

		// 对String，Object，thread等jdk自带类型不起作用
	}

}